home *** CD-ROM | disk | FTP | other *** search
/ SGI Freeware 1999 August / SGI Freeware 1999 August.iso / dist / fw_xemacs.idb / usr / freeware / lib / xemacs-20.4 / lisp / utils / pretty-print.el.z / pretty-print.el
Encoding:
Text File  |  1998-05-21  |  18.6 KB  |  568 lines

  1. ;;   -*- Syntax: Emacs-Lisp; Mode: emacs-lisp -*-
  2. ;; 
  3. ;; Emacs Lisp pretty printer and macro expander
  4. ;; 
  5. ;; Copyright (C) 1992,1993 Guido Bosch <Guido.Bosch@loria.fr>
  6.  
  7. ;; This file is written in GNU Emacs Lisp, but is not part of GNU Emacs.
  8.  
  9. ;; This file is part of XEmacs.
  10.  
  11. ;; XEmacs is free software; you can redistribute it and/or modify it
  12. ;; under the terms of the GNU General Public License as published by
  13. ;; the Free Software Foundation; either version 2, or (at your option)
  14. ;; any later version.
  15.  
  16. ;; XEmacs is distributed in the hope that it will be useful, but
  17. ;; WITHOUT ANY WARRANTY; without even the implied warranty of
  18. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  19. ;; General Public License for more details.
  20.  
  21. ;; You should have received a copy of the GNU General Public License
  22. ;; along with XEmacs; see the file COPYING.  If not, write to the Free
  23. ;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
  24. ;; 02111-1307, USA.
  25.  
  26. ;;; Synched up with:  Not in FSF.
  27.  
  28. ;; Please send bugs and comments to the author.
  29. ;;
  30. ;; <DISCLAIMER>
  31. ;; This program is still under development.  Neither the author nor
  32. ;; CRIN-INRIA accepts responsibility to anyone for the consequences of
  33. ;; using it or for whether it serves any particular purpose or works
  34. ;; at all.
  35. ;; 
  36. ;; The package has been developed under Lucid Emacs 19, but also runs
  37. ;; on Emacs 18, if it is compiled with the version 19 byte compiler
  38. ;; (function `compiled-function-p' lacking).
  39. ;;
  40.  
  41. ;; Installation and Usage
  42. ;; ----------------------
  43. ;;
  44. ;; This package provides an Emacs Lisp sexpression pretty printer and
  45. ;; macroexpander.  To install it, put the following line in your .emacs,
  46. ;; default.el or site-init.el/site-run.el (for Lucid Emacs): 
  47. ;; (require 'pp)
  48. ;; 
  49. ;; The package can also be made autoloadable, with the following entry 
  50. ;; points: 
  51. ;; (autoload 'pp-function "pp" nil t)
  52. ;; (autoload 'pp-variable "pp" nil t)
  53. ;; (autoload 'pp-plist     "pp" nil t)
  54. ;; (autoload 'macroexpand-sexp "pp" nil t)
  55. ;; (autoload 'macroexpand-all-sexp "pp" nil t)
  56. ;; (autoload 'prettyexpand-sexp "pp" nil t)
  57. ;; (autoload 'prettyexpand-all-sexp "pp" nil t)
  58. ;;
  59. ;;(define-key emacs-lisp-mode-map '(control meta m) 'macroexpand-sexp)
  60. ;;(define-key emacs-lisp-mode-map '(control meta M) 'macroexpand-all-sexp)
  61. ;;(define-key emacs-lisp-mode-map '(control symbol m) 'prettyexpand-sexp)
  62. ;;(define-key emacs-lisp-mode-map '(control symbol M) 'prettyexpand-all-sexp)
  63. ;;
  64. ;;(define-key lisp-interaction-mode-map '(control meta m) 'macroexpand-sexp)
  65. ;;(define-key lisp-interaction-mode-map '(control meta M) 'macroexpand-all-sexp)
  66. ;;(define-key lisp-interaction-mode-map '(control symbol m) 'prettyexpand-sexp)
  67. ;;(define-key lisp-interaction-mode-map '(control symbol M) 'prettyexpand-all-sexp)
  68. ;;
  69.  
  70. ;; Pretty printing of the different cells of a symbol is done with the
  71. ;; commands:
  72. ;;
  73. ;;         M-x pp-function
  74. ;;         M-x pp-variable
  75. ;;        M-x pp-plist
  76. ;;
  77. ;; They print a symbol's function definition, variable value and
  78. ;; property list, respectively.  These commands pop up a separate
  79. ;; window in which the pretty printed lisp object is displayed.
  80. ;; Completion for function and variable symbols is provided. If a
  81. ;; function is byte compiled, `pp-function' proposes to call the Emacs
  82. ;; Lisp disassembler (this feature only works for Emacs 19, as it
  83. ;; needs the `compiled-function-p' predicate).
  84. ;;
  85. ;; To use the macro expander, put the cursor at the beginning of the
  86. ;; form to be expanded, then type
  87. ;;
  88. ;;             C-M-m         (macroexpand-sexp)
  89. ;; or        C-M-Sh-M      (macroexpand-all-sexp)
  90. ;; 
  91. ;; Both commands will pop up a temporary window containing the
  92. ;; macroexpanded code. The only difference is that the second command
  93. ;; expands recursively all containing macro calls, while the first one
  94. ;; does it only for the uppermost sexpression.  
  95. ;;     With a prefix argument, the macro expansion isn't displayed in a
  96. ;; separate buffer but replaces the original code in the current
  97. ;; buffer. Be aware: Comments will be lost.
  98. ;;     You can get back the original sexpression using the `undo'
  99. ;;     command on `C-x u'.
  100. ;;
  101. ;; There is also a prettyfied version of the macroexpander:
  102. ;;
  103. ;;        C-Sym-m        (prettyexpand-sexp)
  104. ;; or        C-Sym-M        (prettyexpand-all-sexp)
  105. ;; 
  106. ;; The only difference with the corresponding macroexpand commands is 
  107. ;; that calls to macros specified in the variable
  108. ;; `pp-shadow-expansion-list' are not expanded, in order to make the
  109. ;; code look nicer. This is only useful for Lucid Emacs or code that
  110. ;; uses Dave Gillespies cl package, as it inhibits expansion of the
  111. ;; following macros: block, eval-when, defun*, defmacro*, function*,
  112. ;; setf.
  113.  
  114. ; Change History
  115. ; $Log: pp.el,v $
  116. ; Revision 1.4  1993/03/25  14:09:52  bosch
  117. ; Commands `prettyexpand-sexp' and `prettyexpand-all-sexp' and
  118. ; corresponding key bindings added.  Commands pp-{function, variable}
  119. ; rewritten. `pp-plist' added. Function `pp-internal-loop' (for Dave
  120. ; Gillespies CL loop macro) added.
  121. ;
  122. ; Revision 1.3  1993/03/03  12:24:13  bosch
  123. ; Macroexpander rewritten. Function `pp-macroexpand-all' added (snarfed
  124. ; from Dave Gillespies cl-extra.el). Pretty printing for top level
  125. ; defining forms added (`pp-internal-def'). Key bindings for
  126. ; `emacs-lisp-mode-map' and `lisp-interaction-mode-map' added.  Built-in
  127. ; variable `print-gensym' set for printinng uninterned symbols. Started
  128. ; adding support for cl-dg (defun*, defmacro*, ...).  Minor bug fixes.
  129. ;
  130. ; Revision 1.2  1993/02/25  17:35:02  bosch
  131. ; Comments about Emacs 18 compatibility added.
  132. ;
  133. ; Revision 1.1  1993/02/25  16:55:01  bosch
  134. ; Initial revision
  135. ;
  136. ;
  137.  
  138.  
  139. ;; TO DO LIST
  140. ;; ----------
  141. ;; Provide full Emacs 18 compatibility.
  142.  
  143. ;; Popper support
  144. (defvar pp-buffer-name "*Pretty Print*")
  145. (defvar pp-macroexpand-buffer-name "*Macro Expansion*")
  146. (if (featurep 'popper)
  147.     (or (eq popper-pop-buffers 't)
  148.     (setq popper-pop-buffers 
  149.           (cons pp-buffer-name 
  150.             (cons pp-macroexpand-buffer-name 
  151.               popper-pop-buffers)))))
  152.  
  153. ;; User level functions
  154. ;;;###autoload
  155. (defun pp-function (symbol)
  156.   "Pretty print the function definition of SYMBOL in a separate buffer"
  157.   (interactive 
  158.    (list (pp-read-symbol 'fboundp "Pretty print function definition of: ")))
  159.   (if (compiled-function-p (symbol-function symbol))
  160.       (if (y-or-n-p 
  161.        (format "Function %s is byte compiled. Disassemble? " symbol))
  162.       (disassemble (symbol-function symbol))
  163.     (pp-symbol-cell symbol 'symbol-function))
  164.     (pp-symbol-cell symbol 'symbol-function)))
  165.  
  166. ;;;###autoload
  167. (defun pp-variable (symbol)
  168.   "Pretty print the variable value of SYMBOL in a separate buffer"
  169.   (interactive
  170.    (list (pp-read-symbol 'boundp "Pretty print variable value of: ")))
  171.   (pp-symbol-cell symbol 'symbol-value))
  172.  
  173. ;;;###autoload
  174. (defun pp-plist (symbol)
  175.   "Pretty print the property list of SYMBOL in a separate buffer"
  176.   (interactive
  177.    (list (pp-read-symbol 'symbol-plist "Pretty print property list of: ")))
  178.   (pp-symbol-cell symbol 'symbol-plist))
  179.  
  180. (defun pp-read-symbol (predicate prompt)
  181.   "Read a symbol for which  PREDICATE is true, promptiong with PROMPT."
  182.   (let (symbol)
  183.     (while (or (not symbol) (not (funcall predicate symbol)))
  184.       (setq symbol 
  185.         (intern-soft 
  186.          (completing-read
  187.           prompt
  188.           obarray
  189.           predicate
  190.           t
  191.           (and symbol (symbol-name symbol))))))
  192.     symbol))
  193.  
  194. (defun pp-symbol-cell (symbol accessor)  
  195.   "Pretty print the contents of the cell of SYMBOL that can be reached
  196. with the function ACCESSOR."
  197.   (with-output-to-temp-buffer pp-buffer-name
  198.     (set-buffer pp-buffer-name)
  199.     (emacs-lisp-mode)
  200.     (erase-buffer)
  201.     (pp-internal 
  202.      (funcall accessor symbol) 
  203.      (format "%s's %s is:\n" symbol accessor))
  204.     (terpri)))
  205.  
  206.  
  207.   
  208. ;; Macro expansion (user level)
  209.  
  210. ;;;###autoload
  211. (defun macroexpand-sexp (&optional replace)
  212.   "Macro expand the sexpression following point. Pretty print expansion in a
  213. temporary buffer. With prefix argument, replace the original
  214. sexpression by its expansion in the current buffer."
  215.   (interactive "P")
  216.   (pp-macroexpand-internal 'macroexpand replace t))
  217.  
  218. ;;;###autoload
  219. (defun macroexpand-all-sexp (&optional replace)
  220.   "Macro expand recursively the sexpression following point. Pretty print
  221. expansion in a temporary buffer. With prefix argument, replace the
  222. original sexpression by its expansion in the current buffer."
  223.   (interactive "P")
  224.   (pp-macroexpand-internal 'pp-macroexpand-all replace t))
  225.  
  226. ;;;###autoload
  227. (defun prettyexpand-sexp (&optional replace)
  228.   "Macro expand the sexpression following point. Pretty print expansion
  229. in a temporary buffer. With prefix argument, replace the original
  230. sexpression by its expansion in the current buffer.  
  231.     However, calls to macros specified in the variable
  232. `pp-shadow-expansion-list' are not expanded, in order to make the code
  233. look nicer."
  234.  
  235.   (interactive "P")
  236.   (pp-macroexpand-internal 'macroexpand replace))
  237.  
  238. ;;;###autoload
  239. (defun prettyexpand-all-sexp (&optional replace)
  240.   "Macro expand recursively the sexpression following point. Pretty print
  241. expansion in a temporary buffer. With prefix argument, replace the
  242. original sexpression by its expansion in the current buffer.
  243.     However, calls to macros specified in the variable
  244. `pp-shadow-expansion-list' are not expanded, in order to make the code
  245. look nicer."
  246.   (interactive "P")
  247.   (pp-macroexpand-internal 'pp-macroexpand-all replace))
  248.  
  249. ;; XEmacs: don't do this at load time.
  250. ;;(define-key emacs-lisp-mode-map '(control meta m) 'macroexpand-sexp)
  251. ;;(define-key emacs-lisp-mode-map '(control meta M) 'macroexpand-all-sexp)
  252. ;;(define-key emacs-lisp-mode-map '(control symbol m) 'prettyexpand-sexp)
  253. ;;(define-key emacs-lisp-mode-map '(control symbol M) 'prettyexpand-all-sexp)
  254.  
  255. ;;(define-key lisp-interaction-mode-map '(control meta m) 'macroexpand-sexp)
  256. ;;(define-key lisp-interaction-mode-map '(control meta M) 'macroexpand-all-sexp)
  257. ;;(define-key lisp-interaction-mode-map '(control symbol m) 'prettyexpand-sexp)
  258. ;;(define-key lisp-interaction-mode-map '(control symbol M) 'prettyexpand-all-sexp)
  259.  
  260.  
  261. ;; Macro expansion (internals)
  262.  
  263. (defvar pp-shadow-expansion-list
  264.   (mapcar 'list '(block eval-when defun* defmacro* function* setf))
  265.   "The value of this variable is given as the optional environment
  266. argument of the macroexpand functions. Forms specified in this list are
  267. not expanded.")
  268.  
  269. (defun pp-macroexpand-internal 
  270.   (macroexpand-function replace &optional dont-shadow)
  271.   "Macro expand the sexp that starts at point, using
  272. MACROEXPAND-FUNCTION.  If REPLACE is non-nil, replace the original
  273. text by its expansion, otherwise pretty print the expansion in a
  274. temporary buffer. With optional argument DONT-SHADOW non-nil, do not
  275. use the `pp-shadow-expansion-list' to inhibit expansion of some
  276. forms."
  277.  
  278.   (interactive)
  279.   (let ((expansion
  280.      (funcall 
  281.       macroexpand-function
  282.       (let ((stab (syntax-table)))
  283.         (unwind-protect
  284.         (save-excursion
  285.           (set-syntax-table emacs-lisp-mode-syntax-table)
  286.           ;; (forward-sexp 1)
  287.           (read (current-buffer)))
  288.           (set-syntax-table stab)))
  289.       (if dont-shadow 
  290.           nil
  291.         pp-shadow-expansion-list))))
  292.     (save-excursion
  293.       (if replace 
  294.       (let ((start (point))
  295.         (end (progn (forward-sexp 1) (point))))
  296.         (delete-region start end)
  297.         (pp-internal expansion))
  298.     (with-output-to-temp-buffer pp-macroexpand-buffer-name
  299.       (set-buffer pp-macroexpand-buffer-name)
  300.       (erase-buffer)
  301.       (emacs-lisp-mode)
  302.       (pp-internal expansion))))))
  303.  
  304. ;; Internal pretty print functions
  305.  
  306. (defun pp-internal (form &optional title)
  307.   "Pretty print FORM in in the current buffer.
  308. Optional string TITEL is inserted before the pretty  print."
  309.   (let (start)
  310.     (if title (princ title))
  311.     (setq start (point))
  312.     ;; print-escape-newlines must be t, otherwise we cannot use
  313.     ;; (current-column) to detect good line breaks
  314.     (let ((print-escape-newlines t)
  315.       (print-gensym t)
  316.       )
  317.       (prin1 form (current-buffer))
  318.       (goto-char start)
  319.       (pp-internal-sexp))))
  320.  
  321. (defun pp-internal-sexp ()
  322.   "Pretty print the following sexp. 
  323. Point must be on or before the first character."
  324.  
  325.   (skip-chars-forward " \n\t")
  326.   (let* ((char (following-char))
  327.      (ch-class (char-syntax char))
  328.      (start (point)))
  329.  
  330.     (cond
  331.      ;; open paren
  332.      ((eq char ?\()
  333.       (down-list 1)
  334.       (if (memq  (char-syntax (following-char)) '(?_ ?w))
  335.       (let ((symbol (read (current-buffer))))
  336.         (cond ((fboundp symbol)
  337.            (goto-char start)
  338.            (pp-internal-function symbol))
  339.           ((memq symbol '(lambda macro))
  340.            (pp-internal-lambda))
  341.           (t
  342.            (goto-char start)
  343.            (pp-internal-list))))
  344.     (up-list -1)
  345.     (pp-internal-list)))
  346.      
  347.      ;;symbols & strings
  348.      ((memq  ch-class '(?_        ; symbol
  349.             ?w        ; word
  350.             ?\"        ; string
  351.             ?\\        ; escape
  352.             ?\'        ; quote (for uninterned symbols)
  353.             )) (forward-sexp 1))
  354.     
  355.      ;; vector
  356.      ((eq char ?\[) (pp-internal-list))
  357.      
  358.      ;; error otherwise
  359.      (t (error "pp-internal-sexp: character class not treated yet: `%c'" 
  360.            ch-class)))))
  361.  
  362. (defun pp-internal-function (func)
  363.   "Pretty print a functuion call.
  364. Point must be on the open paren. the function symbol may be passed as an 
  365. optional argument."
  366.   (let ((start (point))
  367.     (too-large (>= (save-excursion
  368.              (forward-sexp 1)
  369.              (current-column))
  370.                fill-column))
  371.     (indent-info (get func lisp-indent-function)))
  372.     (down-list 1)
  373.     ;; skip over function name
  374.     (forward-sexp 1)
  375.     (cond
  376.      ((memq func '(let let*)) (pp-internal-let))
  377.  
  378.      ((eq func 'cond) (pp-internal-cond))
  379.  
  380.      ((memq func '(if while with-output-to-temp-buffer catch block))
  381.       (pp-internal-sexp)
  382.       (pp-internal-body 't))
  383.  
  384.      ((eq func 'quote) (pp-internal-quote))
  385.  
  386.      ((memq func '(progn 
  387.             prog1 prog2
  388.             save-window-excursion 
  389.             save-excursion 
  390.             save-restriction))
  391.       (pp-internal-body 't))
  392.  
  393.      ((memq func '(defun defmacro defsubst defun* defmacro*))
  394.       (pp-internal-def))
  395.      
  396.      ((eq func 'loop) (pp-internal-loop))
  397.  
  398.      ('t (pp-internal-body too-large)))))
  399.  
  400. (defun pp-internal-def ()
  401.   (forward-sexp 1)            ; skip name
  402.   (if (looking-at " nil")        ; replace nil by () 
  403.       (replace-match " ()")
  404.     (forward-sexp 1))
  405.   (if (looking-at " \"")
  406.       ;; comment string. Replace all escaped linefeeds by real ones
  407.       (let ((limit (save-excursion (forward-sexp 1) (point-marker))))
  408.     (newline-and-indent)
  409.     (while (re-search-forward "\\\\n" limit t)
  410.       (replace-match "\n" nil nil))
  411.     (goto-char limit)))
  412.   (pp-internal-body 't))
  413.  
  414. (defun pp-internal-list ()
  415.   "Pretty print a list  or a vector.
  416. Point must be on the open paren."
  417.   (let ((too-large (>= (save-excursion
  418.             (forward-sexp 1)
  419.             (current-column))
  420.               fill-column)))
  421.     (down-list 1)
  422.     (pp-internal-sexp)
  423.     (pp-internal-body too-large)))
  424.  
  425. (defun pp-internal-body (&optional force-indent)
  426.   "Prety print a body of sexp. Stop after reaching a `)'.  If argument
  427. FORCE-INDENT is non-nil, break line after each sexpression of the
  428. body."
  429.   (skip-chars-forward " \n\t")
  430.   (let (ch-class)
  431.     ;; while not closing paren
  432.     (while (/= (setq ch-class (char-syntax (following-char))) ?\)) 
  433.       (if  force-indent (newline-and-indent))
  434.       (pp-internal-sexp))
  435.     (up-list 1)))
  436.  
  437. (defun pp-internal-loop ()
  438.   "Prety print a loop body. Stop after reaching a `)'. 
  439. Line breaks are done before the following keywords: "
  440.   (forward-sexp 1)
  441.   (skip-chars-forward " \n\t")
  442.   (let (ch-class)
  443.     ;; while not closing paren
  444.     (while (/= (setq ch-class (char-syntax (following-char))) ?\))
  445.       (if (not (looking-at "for\\|repeat\\|with\\|while\\|until\\|always\\|never\\|thereis\\|collect\\|append\\|nconc\\|sum\\|count\\|maximize\\|minimize\\|if\\|when\\|else\\|unless\\|do\\W\\|initially\\|finally\\|return\\|named"))
  446.       (pp-internal-sexp)
  447.     (newline-and-indent)
  448.     (forward-sexp 1))
  449.       (skip-chars-forward " \n\t"))
  450.     (up-list 1)))
  451.  
  452. (defun pp-internal-body-list ()
  453.   (let ((too-large (>= (save-excursion
  454.             (forward-sexp 1)
  455.             (current-column))
  456.               fill-column))
  457.     ch-class)
  458.     (down-list 1)
  459.     (pp-internal-sexp)
  460.     (while (/= (setq ch-class (char-syntax (following-char))) ?\)) 
  461.       (if  too-large (newline-and-indent))
  462.       (pp-internal-sexp))
  463.     (up-list 1)))
  464.     
  465. (defun pp-internal-lambda ()
  466.   (forward-sexp 1) ; arguments
  467.   (pp-internal-body 't))
  468.  
  469. (defun pp-internal-let ()
  470.   "Pretty print a let-like  form.
  471. Cursor is behind funtion symbol."
  472.   (down-list 1)
  473.   (while (not (= (following-char) ?\)))
  474.     (if (= (following-char) ?\()
  475.     (pp-internal-body-list)
  476.       (forward-sexp 1))
  477.     (if (not (= (following-char) ?\)))
  478.         (newline-and-indent)))
  479.   (up-list 1)
  480.   (pp-internal-body 't))
  481.  
  482. (defun pp-internal-cond ()
  483.   "Pretty print a cond-like  form.
  484. Cursor is behind funtion symbol."
  485.   (skip-chars-forward " \n\t")
  486.   (while (not (= (following-char) ?\)))
  487.     (pp-internal-body-list)
  488.     (if (not (= (following-char) ?\)))
  489.     (newline-and-indent)))
  490.   (up-list 1))
  491.  
  492.       
  493. (defun pp-internal-quote ()
  494.   "Pretty print a quoted list.
  495. Cursor is behind the symbol quote."
  496.   (skip-chars-forward " \n\t")
  497.   (let ((end (point)))
  498.     (backward-sexp 1)
  499.     (delete-region (point) end)
  500.     (up-list -1)
  501.     (setq end (point))
  502.     (forward-sexp 1)
  503.     (delete-char -1)
  504.     (goto-char end)
  505.     (delete-char 1)
  506.     (insert "'")
  507.     (if (= (char-syntax (following-char)) ?\()
  508.     ;; don't print it as sexp, because it could be (let ... ) or
  509.     ;; (cond ... ) or whatever. 
  510.     (pp-internal-list)
  511.       (pp-internal-sexp))))
  512.  
  513.  
  514. ;; Stolen form Dave Gillespies cl-extra.el
  515. (defun pp-macroexpand-all (form &optional env)
  516.   "Expand all macro calls through a Lisp FORM.
  517. This also does some trivial optimizations to make the form prettier."
  518.   (setq form (macroexpand form env))
  519.   (cond 
  520.    ((not (consp form)) form)
  521.    ((memq (car form) '(let let*))
  522.     (if (null (nth 1 form))
  523.     (pp-macroexpand-all (cons 'progn (cdr (cdr form))) env)
  524.       (cons (car form) 
  525.         (cons (pp-macroexpand-lets (nth 1 form) env)
  526.           (pp-macroexpand-body (cdr (cdr form)) env)))))
  527.    ((eq (car form) 'cond)
  528.     (cons (car form)
  529.       (mapcar (function (lambda (x) (pp-macroexpand-body x env)))
  530.           (cdr form))))
  531.    ((eq (car form) 'condition-case)
  532.     (cons (car form)
  533.       (cons (nth 1 form)
  534.         (cons (pp-macroexpand-all (nth 2 form) env)
  535.               (pp-macroexpand-lets 
  536.                (cdr (cdr (cdr form))) env)))))
  537.    ((memq (car form) '(quote function))
  538.     (if (eq (car-safe (nth 1 form)) 'lambda)
  539.     (list (car form) 
  540.           (cons 'lambda
  541.             (cons (car (cdr (car (cdr form))))
  542.               (pp-macroexpand-body 
  543.                (cdr (cdr (car (cdr form)))) env))))
  544.       form))
  545.    ((memq (car form) '(defun defmacro))
  546.     (cons (car form)
  547.       (cons (nth 1 form)
  548.         (pp-macroexpand-body (cdr (cdr form)) env))))
  549.    ((and (eq (car form) 'progn) (not (cdr (cdr form))))
  550.     (pp-macroexpand-all (nth 1 form) env))
  551.    (t 
  552.     (cons (car form) (pp-macroexpand-body (cdr form) env)))))
  553.  
  554. (defun pp-macroexpand-body (body &optional env)
  555.   (mapcar (function (lambda (x) (pp-macroexpand-all x env))) body))
  556.  
  557. (defun pp-macroexpand-lets (list &optional env)
  558.   (mapcar (function
  559.        (lambda (x)
  560.          (if (consp x) (cons (car x) (pp-macroexpand-body (cdr x) env))
  561.            x))) list))
  562.  
  563. (run-hooks 'pp-load-hook)
  564. (provide 'pp)
  565.  
  566. ;; end pp.el
  567.